/*
Copyright (C) 2007 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// @fileoverview Class and functions for handleing all options dialogs

var optionsDialog = new OptionsDialog();

/**
 * Main class of the options' view to handle all UI and functional stuff
 * The constructor programatically builds parts of the UI which are more
 * eficiently built here rather than the xml
 */
function OptionsDialog() {
  // see which option dialog was opened and act accordingly
  if (options.getValue(OPTION_NAMES.OPTIONS_DIALOG_TYPE) != 'NORMAL') {
    this.borderTimer = null;
    this.borderTarget = null;
    this.objXmlDom = new ActiveXObject('Msxml.DOMDocument');
    var tempPath=gadget.storage.extract('timezones.xml');
    this.objXmlDom.load(tempPath);
    this.xmlParser = new SimpleXmlParser(this.objXmlDom);
    var designId = parseInt(designId = options.getValue(OPTION_NAMES.DESIGN));
    if (isNaN(designId) || designId < 0 || designId >
        CLOCK_INF.DESIGNS.length - 1) {
      designId = 0;
      options.putValue(OPTION_NAMES.DESIGN, 0);
    }
    var backgroundId = parseInt(options.getValue(OPTION_NAMES.BACKGROUND));
    if (isNaN(backgroundId) || backgroundId < 0 ||
        backgroundId > CLOCK_INF.BACKGROUND_NAMES.length - 1) {
      backgroundId = 0;
      options.putValue(OPTION_NAMES.BACKGROUND, 0);
    }
    this.clock = new Clock(optionsAddDiv, designId, backgroundId, 0,
                           cityName.value, true, false);
    if (options.getValue(OPTION_NAMES.OPTIONS_DIALOG_TYPE) == 'EDIT') {
      this.offset = parseInt(options.getValue(OPTION_NAMES.EDIT_CLOCK_OFFSET));
      if (isNaN(this.offset) || this.offset < -HALF_A_DAY ||
          this.offset > HALF_A_DAY) {
        this.offset = 0;
      }
    } else {
      this.offset = null;
    }
    this.selectedCity = null;
    options.putValue(OPTION_NAMES.OPTIONS_DIALOG_TYPE, 'NORMAL');
    optionsChooseLayoutDiv.visible = false;
    view.width = optionsAddDiv.width;
    view.height = optionsAddDiv.height;
    optionsAddDiv.visible = true;
  } else {
    var totalClocks;
    if (isNaN(parseInt(totalClocks =
        options.getValue(OPTION_NAMES.TOTAL_CLOCKS)))) {
      options.putValue(OPTION_NAMES.TOTAL_CLOCKS, 1);
      totalClocks = 1;
    }
    var disableStartingFrom = totalClocks < 9 ? (totalClocks < 3 ? 2 : 4) : 6;
    for (var i = disableStartingFrom; i < 6; ++i) {
      cboLayout.children(i).enabled = false;
      cboLayout.children(i).tooltip =
          cboLayout.children(i).children(0).tooltip = i < 4 ?
          OPTIONS_DISABLED_TWO_LINES : OPTIONS_DISABLED_THREE_LINES;
      cboLayout.children(i).children(0).color = '#666666';
    }
  }
}

/**
 * Called when an options dialog is opened - reads stored options and uses them
 * to finish arranging and drawing the UI
 */
OptionsDialog.prototype.onOpen = function() {
  if (optionsAddDiv.visible) {
    var i = 0;
    for (; i < 60; ++i) {
      if (i < 13) {
        cboOffsetHours.appendElement('<item><label font="Arial" size="9">' +
            (i < 10 ? '0' : '') + i + '</label></item>');
      }
      if (i > 0 && i < 13) {
        cboActualHours.appendElement('<item><label font="Arial" size="9">' +
            (i < 10 ? '0' : '') + i + '</label></item>');
      }
      cboOffsetMinutes.appendElement('<item><label font="Arial" size="9">' +
          (i < 10 ? '0' : '') + i + '</label></item>');
      cboActualMinutes.appendElement('<item><label font="Arial" size="9">' +
          (i < 10 ? '0' : '') + i + '</label></item>');
    }
    for (i = 0; i < CLOCK_INF.DESIGNS.length; ++i) {
      cboDesigns.appendElement('<item><label font="Arial" size="9">' +
          CLOCK_INF.DESIGNS[i].NAME + '</label></item>');
    }
    cboDesigns.selectedIndex = this.clock.designId + 1;
    for (i = 0; i < CLOCK_INF.BACKGROUND_NAMES.length; ++i) {
      cboBackgrounds.appendElement('<item><label font="Arial" size="9">' +
          CLOCK_INF.BACKGROUND_NAMES[i] + '</label></item>');
    }
    cboBackgrounds.selectedIndex = this.clock.backgroundId + 1;
    if (this.offset !== null) {
      cityName.value = options.getValue(OPTION_NAMES.EDIT_CLOCK_LOCATION);
      var selectedCities =
          this.xmlParser.getItems('timeOffset', cityName.value, null, 3);
      for (i = 0; i < selectedCities.length; ++i) {
        if (parseInt(selectedCities[i].value) == this.offset) {
          this.selectedCity = selectedCities[i];
        }
      }
    }
    var countries = this.xmlParser.getItems('country', null, null, 0);
    for (i = 0; i < countries.length; ++i) {
      cboCountry.appendElement('<item selected="' +
          (this.selectedCity !== null ? (this.selectedCity.grandgrandparent ==
          countries[i].name ? 'true' : 'false') : 'false') +
          '"><label font="Arial" size="9">' + (countries[i].name) +
          '</label></item>');
    }
    // editing a clock with the region set to an existing city
    if (this.selectedCity === null && this.offset !== null) {
      cboOffsetSign.selectedIndex = this.offset < 0 ? 1 : 0;
      this.offset = Math.abs(this.offset);
      cboOffsetHours.selectedIndex = Math.floor(this.offset / 60);
      cboOffsetMinutes.selectedIndex = this.offset % 60;
      this.timeZoneChanged(false);
      this.toggleAdvanced();
    // editing a clock with an advanced timezone setting
    } else if (this.selectedCity !== null) {
      this.countryChanged();
    // add a new clock
    } else {
      cboCountry.selectedIndex = cboRegion.selectedIndex =
          cboCity.selectedIndex = cboDesigns.selectedIndex =
          cboBackgrounds.selectedIndex = 0;
      this.cityChanged();
    }
    var now = new Date();
    this.clock.moveTo(27, 205);
    this.clock.setTime(now, true);
    setTimeout(
      function () {
        optionsDialog.onMinuteTimer();
        setInterval(optionsDialog.onMinuteTimer, 30000);
      }, (60 - now.getSeconds()) * 1000);
    setInterval(optionsDialog.onSecondTimer, 1000);
  } else {
    var clockArrangement;
    var showSeconds;
    var shrinkIfIdle;
    if (isNaN(parseInt(clockArrangement =
        options.getValue(OPTION_NAMES.CLOCK_ARRANGEMENT)))) {
      options.putValue(OPTION_NAMES.CLOCK_ARRANGEMENT, 2);
      clockArrangement = 2;
    }
    if (isNaN(parseInt(showSeconds =
        options.getValue(OPTION_NAMES.SHOW_SECONDS)))) {
      options.putValue(OPTION_NAMES.SHOW_SECONDS, 0);
      showSeconds = 0;
    }
    chkShowSeconds.value = (showSeconds == 1);
    if (isNaN(parseInt(showTooltip =
        options.getValue(OPTION_NAMES.SHOW_TOOLTIP)))) {
      options.putValue(OPTION_NAMES.SHOW_TOOLTIP, 0);
      showTooltip = 0;
    }
    chkShowTooltip.value = (showTooltip == 1);
    if (isNaN(parseInt(shrinkIfIdle =
        options.getValue(OPTION_NAMES.SHRINK_IF_IDLE)))) {
      options.putValue(OPTION_NAMES.SHRINK_IF_IDLE, 1);
      shrinkIfIdle = 1;
    }
    chkShrink.value = (shrinkIfIdle == 1);
    if (isNaN(parseInt(shrinkTime.value =
        options.getValue(OPTION_NAMES.SHRINK_TIME)))) {
      options.putValue(OPTION_NAMES.SHRINK_TIME, 10);
      shrinkTime.value = 10;
    }
    if (isNaN(parseInt(shrinkPercent.value =
        options.getValue(OPTION_NAMES.SHRINK_PERCENT)))) {
      options.putValue(OPTION_NAMES.SHRINK_PERCENT, 50);
      shrinkPercent.value = 50;
    }
    cboLayout.selectedIndex = clockArrangement;
    this.drawExamples();
  }
};

/**
 * This function is called every 30 seconds - it sets the exact time
 * of each clock and updates the Actual Time combo boxes
 * It also compensates any errors that the onSecondTimer might have caused
 */
OptionsDialog.prototype.onMinuteTimer = function() {
  var now = new Date();
  var rezult = optionsDialog.clock.setTime(now, true);
  cboActualHours.selectedIndex = ((rezult.hours % 12) + 11) % 12;
  cboActualMinutes.selectedIndex = rezult.minutes;
  cboActualMeridian.selectedIndex = Math.floor(rezult.hours / 12);
};

/**
 * This function gets called every second to update the clocks second handle
 * It also blinks the : between the hours and the minutes of the Actual Time
 */
OptionsDialog.prototype.onSecondTimer = function() {
  optionsDialog.clock.updateSecondHand();
  lblTicker.visible = !lblTicker.visible;
};

/**
 * Called when the OK button is pressed - it stores any changed options
 */
OptionsDialog.prototype.onOk = function() {
  if (optionsAddDiv.visible) {
    options.putValue(OPTION_NAMES.DESIGN, this.clock.designId);
    options.putValue(OPTION_NAMES.BACKGROUND, this.clock.backgroundId);
    options.putValue(OPTION_NAMES.NEW_LOCATION, cityName.value);
    options.putValue(OPTION_NAMES.NEW_OFFSET,
        (1 - 2 * cboOffsetSign.selectedIndex) *
        (cboOffsetHours.selectedIndex * 60 + cboOffsetMinutes.selectedIndex));
  } else {
    options.putValue(OPTION_NAMES.CLOCK_ARRANGEMENT, cboLayout.selectedIndex);
    options.putValue(OPTION_NAMES.SHOW_SECONDS, chkShowSeconds.value ? 1 : 0);
    options.putValue(OPTION_NAMES.SHOW_TOOLTIP, chkShowTooltip.value ? 1 : 0);
    options.putValue(OPTION_NAMES.SHRINK_IF_IDLE, chkShrink.value ? 1 : 0);
    options.putValue(OPTION_NAMES.SHRINK_TIME, shrinkTime.value);
    options.putValue(OPTION_NAMES.SHRINK_PERCENT, shrinkPercent.value);
  }
};

/**
 * Called when the Cancel button is pressed - cleans up a canceled edit dialog
 */
OptionsDialog.prototype.onCancel = function() {
  if (optionsAddDiv.visible) {
    options.putValue(OPTION_NAMES.EDIT_CLOCK_NUM, -1);
  }
};

/**
 * UI function used to efficiently (less code) draw layout examples
 */
OptionsDialog.prototype.drawExamples = function() {
  this.adjustComboBorders(true);
  divExamples.removeAllElements();
  // draw 1 line horizontal layout
  if (cboLayout.selectedIndex === 0) {
    this.drawSmallClocksLine(0, 49, 5, 1);
  }
  // draw 1 line vertical layout
  if (cboLayout.selectedIndex == 1) {
    this.drawSmallClocksLine(66, 0, 1, 1);
    this.drawSmallClocksLine(66, 33, 1, 2);
    this.drawSmallClocksLine(66, 66, 1, 3);
    this.drawSmallClocksLine(66, 99, 1, 4);
  }
  // draw 2 lines horizontal layout
  if (cboLayout.selectedIndex == 2) {
    this.drawSmallClocksLine(0, 33, 5, 1);
    this.drawSmallClocksLine(16, 66, 4, 6);
  }
  // draw 2 lines vertical layout
  if (cboLayout.selectedIndex == 3) {
    this.drawSmallClocksLine(50, 0, 2, 1);
    this.drawSmallClocksLine(50, 33, 2, 3);
    this.drawSmallClocksLine(50, 66, 2, 5);
    this.drawSmallClocksLine(50, 99, 1, 7);
  }
  // draw 3 lines horizontal layout
  if (cboLayout.selectedIndex == 4) {
    this.drawSmallClocksLine(0, 16, 5, 1);
    this.drawSmallClocksLine(0, 49, 5, 6);
    this.drawSmallClocksLine(16, 82, 4, 11);
  }
  // draw 3 lines vertical layout
  if (cboLayout.selectedIndex == 5) {
    this.drawSmallClocksLine(33, 0, 3, 1);
    this.drawSmallClocksLine(33, 33, 3, 4);
    this.drawSmallClocksLine(33, 66, 3, 7);
    this.drawSmallClocksLine(33, 99, 2, 10);
  }
};

/**
 * UI function used to draw a line of clocks - used by drawExamples
 * @param {Integer} startX, startY are the coordinates of the line
 * @param {Integer} numberOfClocks - how many clocks will be drawn in the line
 * @param {Integer} firstClockNumber - the number shown on the label of the
 * first clock all other clocks are consecutive
 */
OptionsDialog.prototype.drawSmallClocksLine = function(startX, startY,
                                                       numberOfClocks,
                                                       firstClockNumber) {
  for (var i = 0; i < numberOfClocks; ++i) {
    divExamples.appendElement('<img x="' + (33 * i + startX) + '" y="' +
                              startY + '" width="31" height="31" ' +
                              'src="images/options_layout.png" />');
    divExamples.appendElement('<label x="' + (33 * i + startX - 1) + '" y="' +
                              startY + '" width="31" height="31" bold="true" ' +
                              'font="arial" size="14" align="center" ' +
                              'vAlign="middle" color="#FFFFFF" >' +
                              (firstClockNumber + i) + '</label>');
  }
};

/**
 * Toggles advanced options on or off
 */
OptionsDialog.prototype.toggleAdvanced = function() {
  optionsAdvancedDiv.visible = cboOffsetSign.visible = cboOffsetHours.visible =
      cboOffsetMinutes.visible = cboActualHours.visible =
      cboActualMinutes.visible = cboActualMeridian.visible =
      !optionsAdvancedDiv.visible;
  optionsSimpleDiv.visible = cboCountry.visible = cboRegion.visible =
      cboCity.visible = !optionsAdvancedDiv.visible;
  linkAdvanced.innerText = optionsAdvancedDiv.visible ?
                           OPTIONS_HIDE_ADVANCED : OPTIONS_ADVANCED;
};

/**
 * Called when the selected design or background in the combo box changes
 */
OptionsDialog.prototype.designChanged = function() {
  if (event.srcElement.selectedIndex === 0) {
    event.returnValue = false;
    return;
  }
  this.adjustComboBorders(true);
  var offsetMinutes = this.clock.offsetMinutes;
  var designId = cboDesigns.selectedIndex ? cboDesigns.selectedIndex - 1 :
                                            this.clock.designId;
  var backgroundId = cboBackgrounds.selectedIndex ?
                     cboBackgrounds.selectedIndex - 1 :
                     this.clock.backgroundId;
  this.clock.destroyClock();
  this.clock = new Clock(optionsAddDiv, designId, backgroundId,
                         offsetMinutes, cityName.value, true, false);
  this.clock.moveTo(27, 205);
  this.onMinuteTimer();
};

/**
 * Called when the selected country in the combo box changes - it updates
 * all other combo boxes to match
 */
OptionsDialog.prototype.countryChanged = function() {
  if (event.srcElement.selectedIndex === 0) {
    event.returnValue = false;
    return;
  }
  this.adjustComboBorders(true);
  cboRegion.clearSelection();
  cboRegion.removeAllElements();
  cboRegion.appendElement('<item enabled="false"><label ' +
                          'font="Arial" bold="true" size="8">' +
                          OPTIONS_REGION + '</label></item>');
  var regions = this.xmlParser.getItems('region',
      cboCountry.selectedItem.children(0).innerText, null, 0);
  for (var i = 0; i < regions.length; ++i) {
    cboRegion.appendElement('<item selected="' + (this.selectedCity !== null ?
                            this.selectedCity.grandparent == regions[i].name ?
                            'true' : 'false' : 'false') +
                            '"><label font="Arial" size="9">' +
                            (regions[i].name) + '</label></item>');
  }
  cboRegion.enabled = cboCity.enabled = true;
  if (this.selectedCity === null) {
    cboRegion.selectedIndex = (cboCity.enabled = regions.length == 1) ? 1 : 0;
    cboCity.opacity = cboCity.enabled ? 255 : 128;
  }
  cboRegion.enabled = regions.length > 1;
  cboRegion.opacity = cboRegion.enabled ? 255 : 128;
  this.regionChanged();
};

/**
 * Called when the selected region in the combo box changes - it updates
 * all other combo boxes to match
 */
OptionsDialog.prototype.regionChanged = function() {
  if (event.srcElement.selectedIndex === 0) {
    event.returnValue = false;
    return;
  }
  this.adjustComboBorders(true);
  cboCity.clearSelection();
  cboCity.removeAllElements();
  cboCity.appendElement('<item tooltip="GMT + 0:00" ' +
                        'enabled="false"><label font="Arial" bold="true" ' +
                        'size="8">' + OPTIONS_CITY + '</label></item>');
  var cities = this.xmlParser.getItems('city',
      cboRegion.selectedItem.children(0).innerText,
      cboCountry.selectedItem.children(0).innerText, 0);
  for (var i = 0; i < cities.length; ++i) {
    var tooltip = 'GMT ' + (cities[i].timeOffset < 0 ? '- ' : '+ ') +
                  (Math.floor(Math.abs(cities[i].timeOffset) / 60)) +
                  ':' + ((Math.abs(cities[i].timeOffset) % 60) / 10) + '0';
    cboCity.appendElement('<item tooltip="' + (tooltip) + '" selected="' +
        (this.selectedCity !== null ? this.selectedCity.parent ==
        cities[i].name ? 'true' : 'false' : 'false') +
        '"><label font="Arial" size="9" tooltip="' + tooltip + '">' +
        (cities[i].name) + '</label></item>');
  }
  cboCity.enabled = cities.length !== 0;
  cboCity.opacity = cboCity.enabled ? 255 : 128;
  if (this.selectedCity !== null) {
    this.selectedCity = null;
    this.cityChanged();
  } else if (cities.length == 1) {
    cboCity.selectedIndex = 1;
    this.cityChanged();
  } else {
    cboCity.selectedIndex = 0;
  }
  cboCity.tooltip = cboCity.selectedIndex > 0 ?
                    cboCity.selectedItem.tooltip : '';
};

/**
 * Called when the selected city in the combo box changes - it updates
 * all other combo boxes to match
 */
OptionsDialog.prototype.cityChanged = function() {
  if (event.srcElement.selectedIndex === 0) {
    event.returnValue = false;
    return;
  }
  this.adjustComboBorders(true);
  var timeZone = cboCity.selectedItem.tooltip;
  cboOffsetSign.selectedIndex = (timeZone.charAt(4) == '-' ? 1 : 0);
  timeZone = timeZone.substring(6);
  timeZone = timeZone.split(':');
  timeZone[0] = parseInt(timeZone[0]);
  timeZone[1] = parseInt(timeZone[1]);
  if (isNaN(timeZone[0]) || isNaN(timeZone[1]) ||
      timeZone[0] < 0 || timeZone[0] > 12 ||
      timeZone[1] < 0 || timeZone[1] > 59) {
    return;
  }
  cboOffsetHours.selectedIndex = timeZone[0];
  cboOffsetMinutes.selectedIndex = timeZone[1];
  if (cboCity.selectedIndex > 0) {
    cityName.value = cboCity.selectedItem.children(0).innerText;
  }
  this.timeZoneChanged(true);
};

/**
 * Called when any timezone combo box selection changes - it updates
 * all other combo boxes to match
 */
OptionsDialog.prototype.timeZoneChanged = function(callFromCity) {
  this.adjustComboBorders(true);
  if (!callFromCity) {
    cboRegion.enabled = cboCity.enabled = false;
    cboRegion.opacity = cboCity.opacity = 128;
    cboCountry.selectedIndex = cboRegion.selectedIndex =
        cboCity.selectedIndex = 0;
  }
  cboOffsetMinutes.enabled = cboOffsetHours.selectedIndex < 12;
  if (!cboOffsetMinutes.enabled) {
    cboOffsetMinutes.selectedIndex = 0;
  }
  cboOffsetMinutes.opacity = cboOffsetMinutes.enabled ? 255 : 128;
  this.clock.offsetMinutes = (1 - 2 * cboOffsetSign.selectedIndex) *
                             (cboOffsetHours.selectedIndex * 60 +
                             cboOffsetMinutes.selectedIndex);
  this.onMinuteTimer();
};

/**
 * Called when any actual time combo box selection changes - it updates
 * all other combo boxes to match
 */
OptionsDialog.prototype.timeChanged = function(callFromTimeZone) {
  this.adjustComboBorders(true);
  if (!callFromTimeZone) {
    var now = new Date();
    now.setMonth(0);  // avoid getting daylight timezones
    var hours = (cboActualHours.selectedIndex + 1) % 12 +
                12 * cboActualMeridian.selectedIndex;
    var offset = hours * 60 + cboActualMinutes.selectedIndex -
                 now.getUTCHours() * 60 - now.getUTCMinutes();
    if (offset < -HALF_A_DAY) {
      offset += 2 * HALF_A_DAY;
    }
    if (offset > HALF_A_DAY) {
      offset -= 2 * HALF_A_DAY;
    }
    cboOffsetSign.selectedIndex = offset < 0 ? 1 : 0;
    offset = Math.abs(offset);
    cboOffsetHours.selectedIndex = Math.floor(offset / 60);
    cboOffsetMinutes.selectedIndex = offset % 60;
    this.timeZoneChanged(false);
  }
};

/**
 * Called when the location name edit box text changes - it updates
 * the preview clock
 */
OptionsDialog.prototype.cityNameChanged = function() {
  this.clock.cityLabel.innerText = cityName.value;
};

/**
 * Called when the shrink if idle checkbox is clicked
 * it enables/disables the edit box for idle time
 */
OptionsDialog.prototype.onShrinkIfIdle = function() {
  shrinkTime.enabled = shrinkPercent.enabled = chkShrink.value;
  shrinkTime.opacity = shrinkPercent.opacity = shrinkTime.enabled ? 255 : 128;
  lblZoomRatio.color = lblZoomPercent.color =
      lblZoomDelay.color = zoomSeconds.color =
      shrinkTime.enabled ? '#000000' : '#676767';
};

/**
 * Called when the edit box for idle time text change
 * it makes sure only numerical characters are inserted
 */
OptionsDialog.prototype.shrinkPressed = function() {
  if (event.keyCode < 48 || event.keyCode > 57) {
    event.returnValue = false;
  } else if ((event.srcElement.name == OPTION_NAMES.SHRINK_TIME &&
            event.srcElement.value.length > 3) ||
           (event.srcElement.name == OPTION_NAMES.SHRINK_PERCENT &&
            event.srcElement.value.length > 1)) {
    event.returnValue = false;
  }
};

/**
 * Called when the edit box for idle time loses focus
 * it makes sure only values in the 5~3600 range get accepted
 */
OptionsDialog.prototype.shrinkLostFocus = function() {
  if (isNaN(parseInt(shrinkTime.value)) || parseInt(shrinkTime.value) < 5) {
    shrinkTime.value = 5;
    alert(ERROR_TIME_TO_SHRINK + ' ' + shrinkTime.value + ' seconds.');
  } else if (parseInt(shrinkTime.value) > 3600) {
    shrinkTime.value = 3600;
    alert(ERROR_TIME_TO_SHRINK + ' ' + shrinkTime.value + ' seconds.');
  } else if (isNaN(parseInt(shrinkPercent.value)) ||
             parseInt(shrinkPercent.value) < 30) {
    shrinkPercent.value = 30;
    alert(ERROR_PERCENT_TO_SHRINK + ' ' + shrinkPercent.value + '%');
  } else if (parseInt(shrinkPercent.value) > 90) {
    shrinkPercent.value = 90;
    alert(ERROR_PERCENT_TO_SHRINK + ' ' + shrinkPercent.value + '%');
  }
};

/**
 * Called to show/hide a border around an open combobox
 */
OptionsDialog.prototype.adjustComboBorders = function(forceHide) {
  var visibility = forceHide ? false : !event.srcElement.dropListVisible;
  if (visibility) {
    /**
     * although all in gadget events are covered, there is the posibility
     * that the user shifts focus from the gadget options to another window
     * which causes combo-boxes to close without onfocusout event - so we set
     * a timer to watch for that
     */
    this.borderTarget = event.srcElement;
    if (this.borderTimer) {
      clearInterval(this.borderTimer);
    }
    this.borderTimer = setInterval(
        function () {
          if (!optionsDialog.borderTarget.dropListVisible) {
            optionsDialog.adjustComboBorders(true);
          }
        }, 250);
    comboBordersLeft.x = comboBordersBottom.x = comboBordersTop.x =
        event.srcElement.x - 1;
    comboBordersLeft.y = comboBordersRight.y = comboBordersTop.y =
        event.srcElement.y + event.srcElement.itemHeight;
    comboBordersBottom.width = comboBordersTop.width =
        event.srcElement.width + 2;
    comboBordersLeft.height = comboBordersRight.height =
        event.srcElement.itemHeight * (event.srcElement.children.count > 9 ?
        9 : event.srcElement.children.count);
    comboBordersRight.x = comboBordersTop.x + comboBordersTop.width - 1;
    comboBordersBottom.y = comboBordersLeft.y + comboBordersLeft.height - 1;
  } else if (this.borderTimer) {
    clearInterval(this.borderTimer);
  }
  comboBordersTop.visible = comboBordersLeft.visible =
      comboBordersRight.visible = comboBordersBottom.visible = visibility;
};
